package com.pkk.cloud.support.gateway.filter;

import static com.pkk.cloud.support.gateway.code.GatewayBusinessCode.SERVICE_NO_REGISTER;
import static com.pkk.cloud.support.gateway.code.GatewayBusinessCode.SERVICE_NO_START;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.pkk.components.rpc.response.util.ResponseUtil;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

/**
 * @description: 网关实现微服务之间调用出现异常的统一处理
 * @author: peikunkun
 * @create: 2020-03-17 13:56
 **/
@Slf4j
@Component
public class ErrorFilter extends ZuulFilter {


  /**
   * pre：可以在请求被路由之前调用 route：在路由请求时候被调用 post：在route和error过滤器之后被调用， error：处理请求时发生错误时被调用
   *
   * @return
   */
  @Override
  public String filterType() {
    //处理请求时发生错误时被调用
    return FilterConstants.ERROR_TYPE;
  }

  @Override
  public int filterOrder() {
    //需要在默认的 SendErrorFilter 之前
    return -1;
  }

  @Override
  public boolean shouldFilter() {
    // 只有在抛出异常时才会进行拦截
    return RequestContext.getCurrentContext().containsKey("throwable");
  }

  @Override
  public Object run() {
    try {
      RequestContext requestContext = RequestContext.getCurrentContext();
      Object e = requestContext.get("throwable");

      if (e != null && e instanceof ZuulException) {
        ZuulException zuulException = (ZuulException) e;
        // 删除该异常信息,不然在下一个过滤器中还会被执行处理
        requestContext.remove("throwable");
        // 响应给客户端信息
        HttpServletResponse response = requestContext.getResponse();
        response.setHeader("Content-type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        response.setCharacterEncoding("UTF-8");
        PrintWriter pw = null;
        pw = response.getWriter();
        int status = response.getStatus();
        String str;
        if (status == 504) {
          str = JSONObject.toJSONString(ResponseUtil.error(SERVICE_NO_REGISTER));
        } else {
          str = JSONObject.toJSONString(ResponseUtil.error(SERVICE_NO_START));
        }
        pw.write(str);
        pw.close();
      }
    } catch (Exception ex) {
      log.error("Exception filtering in custom error filter（网关调用出错）：", ex);
    }
    return null;
  }
}
